<?php
/**
 * Created by JetBrains PhpStorm.
 * User: bicho
 * Date: 16/06/12
 * Time: 10:38
 * To change this template use File | Settings | File Templates.
 */
class BaseMapper
{
    protected $_dbTable;
    protected $_extendedModel;

    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }

    public function setExtendedModel($extendedModel)
    {
        $this->_extendedModel = $extendedModel;
    }

    public function getExtendedModel()
    {
        return $this->_extendedModel;
    }


    /**
     * @return Zend_Db_Table_Abstract
     * @throws Exception
     */

    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            throw new Exception('Invalid table data gateway provided');
        }
        return $this->_dbTable;
    }

    public function save($baseModel, $id = null)
    {
        //TODO review these method
        if ($baseModel instanceof BaseModel) {
            $data = $baseModel->toArray();
            $id = $baseModel->getId();
        } else {
            // in case recieve an array
            $data = $baseModel;
        }

        if (null == $id || $id == 0) {
            unset($data['id']);
            return $this->getDbTable()->insert($data);
        } else {
            return $this->getDbTable()->update($data, array('id = ?' => $id));
        }
    }

    /**
     * @param $id
     * @return _extendedModel
     */
    public function find($id)
    {
        $result = $this->getDbTable()->find($id);
        if (0 == count($result)) {
            return null;
        }
        $row = $result->current();
        return $this->map($row);

    }

    public function fetchAll()
    {
        $resultSet = $this->getDbTable()->fetchAll();
        $entries = array();
        foreach ($resultSet as $row) {
            $entries[] = $this->map($row);
        }
        return $entries;
    }

    /**
     * @param $row
     * @return BaseModel
     */
    public function map($row)
    {
        if ($row == null) {
            return null;
        }
        $methods = get_class_methods($this->_extendedModel);
        $entry = new $this->_extendedModel();
        foreach ($row as $key => $value) {

            $key = $this->getMethodName($key);

            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $entry->$method($value);
            }
        }
        return $entry;
    }

    private function getMethodName($key){
        if (false != ($pos = strpos($key, '_'))) {
            $after_ = substr($key, $pos + 1);
            $key = substr($key, 0, $pos) . ucfirst($after_);
        }
        if(false != ($pos = strpos($key, '_'))){
           return $this->getMethodName($key);
        }
        return $key;
    }


    protected function mapSelect($select, $as_array = false)
    {
        $result = $this->getDbTable()->fetchAll($select);
        if ($result->count() == 0) {
            return array();
        } else if ($result->count() > 1 || $as_array) {
            $entries = array();
            foreach ($result as $row) {
                $entries[] = $this->map($row);
            }
            return $entries;
        } else {
            $row1 = $result->toArray();
            return $this->map($row1[0]);
        }
    }
}
